from  common import definesymbols
from automatadefs import  fsa,epsilon,EMPTYSET
from graphics import draw,automaton2page
from operations import trim,ac,coac,parallel,union,concatenation,invproj,complement,setminus,epsilonobserver
from operations import plusclosuregen,kleeneclos,product,renstates
from diagnosis import labelfailaut



def aut2monoid(auto):
        
    delta = auto.delta
    numStates=len(auto.X)   
     
    def compute_new_transition(transition,event):        
        nextTransition = []
        nextTranString =''
        for state in transition:
            if state <> '0':
                nextState = delta(state,event)
                if nextState == None :
                    nextState = '0'
            else:
                nextState = '0'
                                                       
            nextTransition.append(nextState)
            nextTranString = nextTranString+','+str(nextState)
            nextTranString = nextTranString.lstrip(',')
        return nextTransition, nextTranString
    
    def is_failure_trans(transition):
        failure = True
        numTrans = [int(s) for s in transition]
        sum = reduce(lambda x, y:  x+y, numTrans )
        if sum == 0:
            return False
        for s in numTrans:
           if ((s <> 0) & (s < numStates)):
               failure = False               
        return failure
    
    def is_ok_trans(transition):
        oktrans = True
        numTrans = [int(s) for s in transition]
        sum = reduce(lambda x, y:  x+y, numTrans )
        if sum == 0:
            return False
        for s in numTrans:
           if ((s <> 0) & (s >= numStates)):
               oktrans = False               
        return oktrans
           
    
    Xord = list(auto.X)
    Xord.sort()
    Eord = list(auto.E)
    Eord.sort()    
    sizeofMonoid=len(Xord)        
    transMonoid=[]
    representative=[epsilon]+Eord
    Yrep = []
    Nrep = []
    transMonoid.append(Xord)
    relations={}
    dictRepres={}
    newTransition,strnewTransition = compute_new_transition(Xord,epsilon)        

    invdictMonoid={strnewTransition:epsilon}
    index=1
    rightCayleyTrans=[]
    leftCayleyTrans=[]
    
        
    for event in Eord:
        dictRepres[event]=index
        transition = transMonoid[0]  
        newTransition,strnewTransition=compute_new_transition(transition,event)
        if is_failure_trans(newTransition):
            Yrep.append(event) 
        elif is_ok_trans(newTransition):
            Nrep.append(event)
                   
        invdictMonoid[strnewTransition]=event
        transMonoid.append(newTransition)  
        rightCayleyTrans.append([epsilon,event,event])  
        leftCayleyTrans.append([epsilon,event,event])   
        index+=1
    
    
    actRepresList = Eord     
    lenghtLastRepres=1
    leftCayleyTrans
    nullTransition=['0' for state in Xord]
    zero=[]
    
    while (lenghtLastRepres <= sizeofMonoid) & (actRepresList <> [])  :        
        newCandList=[]             

        for actRepres in actRepresList:                                    
            for event in Eord:                
                transition = transMonoid[dictRepres[actRepres]]           
                newTransition,strnewTransition=compute_new_transition(transition,event)
                newRepres=actRepres+'*'+event 
                newLeftRepres=event+'*'+actRepres

                if not invdictMonoid.has_key(strnewTransition) :                  
                    transMonoid.append(newTransition)                    
                    if newTransition == nullTransition:
                        zero.append(newRepres)                                                                   
                    representative.append(newRepres)
                    if is_failure_trans(newTransition):
                        Yrep.append(newRepres) 
                    elif is_ok_trans(newTransition):
                        Nrep.append(newRepres)                          
                    dictRepres[newRepres]=index 
                    invdictMonoid[strnewTransition] = newRepres    
                    newCandList.append(newRepres)
                    rightCayleyTrans.append([actRepres,event,newRepres])                          
                    index+=1
                else:
                    equivalent = invdictMonoid[strnewTransition]
                    rightCayleyTrans.append([actRepres,event,equivalent])                   
                    relations.update({newRepres:equivalent})
                    dictRepres[newRepres]=dictRepres[actRepres]                    
              
        actRepresList = newCandList              
        lastRepres = newRepres.replace('*','')
        lenghtLastRepres =len(lastRepres)
        
    
    Xc=representative
    X0c=[epsilon]
    Xmc=[]    
    rightCayleyAut =fsa(Xc,Eord,rightCayleyTrans,X0c,
                        Xmc,Eobs=auto.Eobs,Econ=auto.Econ,type='result')
 
     # calculating idempotents
    
    idempotents=[]
    for state in representative[1:]:
        sequence=state.split('*')
        result = rightCayleyAut.delta(state,sequence)
        if state == result:
            idempotents.append(state)

  #  calculating transitions for leftCayleyGraph
    
    for actRepres in representative[1:]:
        for event in Eord:
            leftResult= [event]+actRepres.split('*')
            nextRepres=rightCayleyAut.delta(epsilon,leftResult)
            leftCayleyTrans.append([actRepres,event,nextRepres])
    
    leftCayleyAut =fsa(Xc,Eord,leftCayleyTrans,X0c,Xmc,
                       Eobs=auto.Eobs,Econ=auto.Econ,type='plant')    
    
    Yrep=set(Yrep)
    Nrep=set(Nrep)
    representative=set(representative)           
    return relations,representative,rightCayleyAut,leftCayleyAut,idempotents,zero,Yrep,Nrep



#a,b,c,d,e,sf,x0,x1,x2,x3,x4,x5,x6,x7 = definesymbols('a b c d e sf 0 1 2 3 4 5 6 7')
#sigma=set([a,b,c,d,e,sf])
#sigmaf=set([sf])
#X=[x1,x2,x3,x4,x5,x6,x7]
#X0=[x1]
#Xm=[]
#transicoes=[[x1,c,x2],[x1,a,x5],[x2,sf,x3],[x3,b,x4],
#            [x4,d,x4],[x1,a,x5],[x5,b,x6],[x6,d,x6],[x7,e,x7],[x3,a,x7]]
#sigmaobs=[a,b,c,d,e]


#####################   example number 1

#a,b,sf,x1,x2,x3,x4,x5 = definesymbols('a b sf 1 2 3 4 5')
#sigma=set([a,b,sf])
#sigmaf=set([sf])
#X=[x1,x2,x3,x4,x5]
#X0=[x1]
#Xm=[]
#transicoes=[[x1,sf,x2],[x1,a,x3],[x2,a,x4],[x3,b,x5],
#            [x4,b,x4],[x5,b,x5]]
#sigmaobs=[a,b]
#
#
#G1=fsa(X,sigma,transicoes,X0,Xm,[],sigmaobs,name='$G_n$') 
#Al=labelfailaut(sf)
#G1prim=G1//Al
#mapping=[]
#countNormal = 1
#countFail = 1
#offset=len(G1prim.X)
#
#for state in G1prim.X:
#    x1, x2 = state
#    if x2 == 'N':
#        mapping.append((state,str(countNormal)))
#        countNormal +=1
#    if x2 == 'Y':
#        mapping.append((state,str(offset+countFail)))
#        countFail +=1
#
#G11prim=renstates(G1prim,mapping)
#rels,reps,rcayley,lcayley,idems,zero,fail=aut2monoid(G11prim)
#fail=set(fail)
#reps=set(reps)
#print reps-fail
#print fail

####################   example number 2

a,b,c,d,e,sf,x1,x2,x3,x4,x5,x6 = definesymbols('a b c d e sf 1 2 3 4 5 6')
sigma=[a,b,c,d,e,sf]
X=[x1,x2,x3,x4,x5,x6]
X0=[x1]
Xm=[]
transicoes=[[x1,sf,x2],[x1,b,x3],[x2,b,x4],[x3,a,x5],[x3,c,x3],
            [x4,c,x4],[x4,d,x6],[x5,b,x5],[x6,e,x6]]
sigmaobs=[a,b,c,d,e]
G1=fsa(X,sigma,transicoes,X0,Xm,[],sigmaobs,name='$G_n$')

Al=labelfailaut(sf)
G1prim=parallel(G1,Al,'tuple')
mapping=[]
countNormal = 1
countFail = 1
offset=len(G1prim.X)
#
for state in G1prim.X:
    x1, x2 = state
    if x2 == 'N':
        mapping.append((state,str(countNormal)))
        countNormal +=1
    if x2 == 'Y':
        mapping.append((state,str(offset+countFail)))
        countFail +=1

G11prim=renstates(G1prim,mapping)
rels,reps,rcayley,lcayley,idems,zero,Yrep,Nrep=aut2monoid(G11prim)

#reps=reps-set([epsilon])
#incert=reps-Yrep-Nrep
#print reps
#print Yrep
#print Nrep
#print incert

############### example number 3

#a,b,c,d,e,sf,x0,x1,x2,x3,x4,x5,x6,x7 = definesymbols('a b c d e sf 0 1 2 3 4 5 6 7')
#sigma=set([a,b,c,d,e,sf])
#sigmaf=set([sf])
#X=[x1,x2,x3,x4,x5,x6,x7]
#X0=[x1]
#Xm=[]
#transicoes=[[x1,c,x2],[x1,a,x5],[x2,sf,x3],[x3,b,x4],
#            [x4,d,x4],[x1,a,x5],[x5,b,x6],[x6,d,x6],[x7,e,x7],[x3,a,x7]]
#sigmaobs=[a,b,c,d,e]
#reps=reps-set([epsilon])
#incert=reps-Yrep-Nrep
#print reps
#print Yrep
#print Nrep
#print incert

############## example number 4



a,b,c,d,f,q0,q1,q2,q3,q4,q5 = definesymbols('a b c d f q_0 q_1 q_2 q_3 q_4 q_5')
sigma=set([a,b,c,d,f])
sigmaf=set([f])
X=[q0,q1,q2,q3,q4,q5]
X0=[q0]
Xm=[q0]
transicoes=[[q0,a,q1],[q1,f,q3],[q1,b,q2],[q2,a,q1],
            [q2,d,q4],[q3,b,q5],[q4,a,q4],[q5,c,q4]]
sigmaobs=[a,b,c,d]
G1=fsa(X,sigma,transicoes,X0,Xm,[],sigmaobs,name='$G_n$')

Al=labelfailaut(f)
G1prim=parallel(G1,Al,'tuple')
mapping=[]
countNormal = 1
countFail = 1
offset=len(G1prim.X)

for state in G1prim.X:
    x1, x2 = state
    if x2 == 'N':
        mapping.append((state,str(countNormal)))
        countNormal +=1
    if x2 == 'Y':
        mapping.append((state,str(offset+countFail)))
        countFail +=1

G11prim=renstates(G1prim,mapping)
rels,reps,rcayley,lcayley,idems,zero,Yrep,Nrep=aut2monoid(G11prim)


# we should work again , problem is solved.


draw(G1prim&rcayley,G1prim)

